<script setup>
import { onMounted, ref, onUnmounted } from "vue";
import "cesium/Build/Cesium/Widgets/widgets.css";
import * as Cesium from "cesium";
import SnowEffect from "@/utils/cesiumCtrl/snow.js";
import { ElNotification } from "element-plus";

let viewer = null;
let snow = null;
let planeGltf = null;
const active = ref(1);

defineProps({
  msg: String,
});

onMounted(async () => {
  initCesium();
  setTimeout(() => {
    loadPlaneGltf();
  }, 3000);
});

const initCesium = () => {
  Cesium.Ion.defaultAccessToken =
    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2MzU4NzcwYS0yYjhjLTQ3ZTYtOGM4OC0yMjViMzg5YWNiM2MiLCJpZCI6MTgxMzU5LCJpYXQiOjE3MDE3MDIxNTd9.nMroTGyHYS7g3jjRX2HMLkAA1bbHMfEuTBLH2BCYAuM";
  viewer = new Cesium.Viewer("scene", {
    animation: false, // 动画小组件
    baseLayerPicker: false, // 底图组件，选择三维数字地球的底图（imagery and terrain）。
    fullscreenButton: false, // 全屏组件
    vrButton: false, // VR模式
    geocoder: false, // 地理编码（搜索）组件
    homeButton: false, // 首页，点击之后将视图跳转到默认视角
    infoBox: false, // 信息框
    sceneModePicker: false, // 场景模式，切换2D、3D 和 Columbus View (CV) 模式。
    selectionIndicator: false, // 是否显示选取指示器组件
    timeline: true, // 时间轴
    navigationHelpButton: false, // 帮助提示，如何操作数字地球。
    // 如果最初应该看到导航说明，则为true；如果直到用户明确单击该按钮，则该提示不显示，否则为false。
    navigationInstructionsInitiallyVisible: false,
    shadows: true,
    shouldAnimate: true,
    brightness: 0.8,
    contrast: 1.5,
  });

  viewer._cesiumWidget._creditContainer.style.display = "none";

  //1.Cesium加载高德矢量地图

  const layer = new Cesium.UrlTemplateImageryProvider({
    url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",

    minimumLevel: 4,

    maximumLevel: 18,
  });

  const imgLayer = new Cesium.UrlTemplateImageryProvider({
    url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",

    minimumLevel: 3,

    maximumLevel: 18,
  });

  //viewer.imageryLayers.addImageryProvider(imgLayer);

  //3.Cesium加载注记要素

  const annLayer = new Cesium.UrlTemplateImageryProvider({
    url: "http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8",

    minimumLevel: 3,

    maximumLevel: 18,
  });

  viewer.imageryLayers.addImageryProvider(annLayer);
  // 外天空盒
  viewer.scene.skyBox = new Cesium.SkyBox({
    sources: {
      positiveX: "/Standard-Cube-Map/px1.png",
      negativeX: "/Standard-Cube-Map/nx1.png",
      positiveY: "/Standard-Cube-Map/pz.png",
      negativeY: "/Standard-Cube-Map/nz1.png",
      positiveZ: "/Standard-Cube-Map/py.png",
      negativeZ: "/Standard-Cube-Map/ny1.png",
    },
  });

  snow = new SnowEffect(viewer, {
    snowSize: 0.02, // 雪花大小
    snowSpeed: 60.0, // 雪速
  });
  snow.show(true);
  active.value = 1;
};

const loadPlaneGltf = () => {
  snow.destroy();
  active.value = 2;
  ElNotification({
    message: "开始加载飞机",
    type: "success",
    duration: 4000,
  });
  flyToFun(() => {
    addGLTFModel("/plane/plane.glb", 10000);
    active.value = 3;
    setTimeout(() => {
      active.value = 4;
      ElNotification({
        message: "自动巡航",
        type: "success",
        duration: 4000,
      });
      planeLineRoute();
    }, 3000);
  });
};

const flyToFun = (callback) => {
  //飞行到给定的经纬度飞往声谷
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(117.12135, 31.818807, 40000.0), //117.022215,31.862739
    orientation: {
      heading: Cesium.Math.toRadians(0),
      pitch: Cesium.Math.toRadians(-90),
      roll: 0.0,
    },
    duration: 5.0, // 飞行时间（秒）
    complete: callback,
  });
};

async function addGLTFModel(url, height) {
  // Entity方法加载gltf
  viewer.entities.removeAll(); //加载之前先清楚所有entity
  const position = Cesium.Cartesian3.fromDegrees(116.977669, 31.789776, height);
  const heading = 0; //135度转弧度
  const pitch = Cesium.Math.toRadians(0);
  const roll = 0;
  const hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
  const orientation = Cesium.Transforms.headingPitchRollQuaternion(
    position,
    hpr
  );
  planeGltf = await viewer.entities.add({
    name: "feiji",
    position: position,
    orientation: orientation,
    model: {
      uri: url, //注意entitits.add方式加载gltf文件时，这里是uri，不是url，并且这种方式只能加载.glb格式的文件
      minimumPixelSize: 1000, //最小像素大小，可以避免太小看不见
      maximumScale: 20000, //模型的最大比例尺大小。minimumPixelSize的上限
    },
  });
  viewer.trackedEntity = planeGltf; // 聚焦模型
  ElNotification({
    message: "加载飞机完成",
    type: "success",
    duration: 4000,
  });
}

const planeLineRoute = () => {
  // 116.977669,31.789776 （左） 117.119633,31.879321（上） 117.274987,31.814431（右）    117.230784,31.817604  （下）

  const flightData = [
    { longitude: 116.977669, latitude: 31.789776, height: 40000.0, time: 0 },
    { longitude: 114.304569, latitude: 30.593354, height: 50000.0, time: 1000 },
    { longitude: 117.02962, latitude: 30.52417, height: 40000.0, time: 3000 },
    { longitude: 118.347792, latitude: 31.344173, height: 40000.0, time: 6000 },
    { longitude: 117.249159, latitude: 31.442643, height: 40000.0, time: 6000 },

    // 添加更多的轨迹点...
  ];
  /*   * 设所有雷达坐标的间隔均为30s，以此计算总的航班持续时间
   * 算出航班的开始时间和结束时间，其中开始时间为已知的航班出发时间，结束时间是开始时间和总持续时间的总和
   * 通过将航班的开始和结束时间设置为起点和终点来初始化取景器的计时器
   * 同时将取景器的当前时间设置为计时器开始时间  */

  const timeStepInSeconds = 300;
  const totalSeconds = timeStepInSeconds * (flightData.length - 1);
  const start = Cesium.JulianDate.fromIso8601("2023-12-01T23:10:00Z");
  const stop = Cesium.JulianDate.addSeconds(
    start,
    totalSeconds,
    new Cesium.JulianDate()
  );
  viewer.clock.startTime = start.clone();
  viewer.clock.stopTime = stop.clone();
  viewer.clock.currentTime = start.clone();
  viewer.timeline.zoomTo(start, stop);
  // Speed up the playback speed 50x.
  viewer.clock.multiplier = 50; //时间速率
  // Start playing the scene.
  viewer.clock.shouldAnimate = true;
  // viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //循环执行
  const positionProperty = new Cesium.SampledPositionProperty();
  flightData.forEach(function (dataPoint, i) {
    const time = Cesium.JulianDate.addSeconds(
      start,
      i * timeStepInSeconds,
      new Cesium.JulianDate()
    );
    //或者根据给定的时间进行插值
    //const time=Cesium.JulianDate.addSeconds("start,dataPoint[i].time,new Cesium.JulianDate())");
    const position = Cesium.Cartesian3.fromDegrees(
      dataPoint.longitude,
      dataPoint.latitude,
      dataPoint.height
    );
    // Store the position along with its timestamp.
    // Here we add the positions all upfront, but these can be added at run-time as samples are received from a server.
    positionProperty.addSample(time, position);
    viewer.entities.add({
      description: `Location: (${dataPoint.longitude}, ${dataPoint.latitude}, ${dataPoint.height})`,
      position: Cesium.Cartesian3.fromDegrees(
        dataPoint.longitude,
        dataPoint.latitude,
        dataPoint.height
      ),
      point: { pixelSize: 10, color: Cesium.Color.RED },
    });
  });

  // 更新飞机实体的 SampledPositionProperty
  planeGltf.position = positionProperty;
  planeGltf.orientation = new Cesium.VelocityOrientationProperty(
    positionProperty
  );
  // viewer.clock.shouldAnimate = false;
  //viewer.trackedEntity = planeGltf;
};

onUnmounted(() => {
  snow.destroy();
});
</script>

<template>
  <div id="scene" style="height: 100vh; width: 100vw; overflow: hidden">
    <div class="timeLine" style="height: 300px; max-width: 600px">
      <el-steps direction="vertical" :active="active" finish-status="success">
        <el-step title="一" description="渲染环境" />
        <el-step title="二" description="开始加载飞机" />
        <el-step title="三" description="加载飞机完成" />
        <el-step title="四" description="自动巡航" />
      </el-steps>
    </div>
  </div>
</template>

<style scoped>
.read-the-docs {
  color: #888;
}

.botton {
  z-index: 1;
  position: absolute;
  top: 20px;
  left: 20px;
}

.timeLine {
  position: absolute;
  top: 50%;
  right: 10%;
  transform: translateY(-50%);
  width: 100px;
  height: 500px;

  z-index: 20;
}
</style>
